package com.dd.stack.file.service.internal.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dd.stack.common.util.ResultEnum;
import com.dd.stack.file.config.exception.DomainException;
import com.dd.stack.file.mapper.file.FileMapper;
import com.dd.stack.file.pojo.DO.FileDO;
import com.dd.stack.file.pojo.VO.FileVO;
import com.dd.stack.file.pojo.req.FilePageReq;
import com.dd.stack.file.service.internal.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @Author liuxianmeng
 * @CreateTime 2025/4/1 1:02
 * @Description 类功能作用说明
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {

    @Value("${server.file.upload-path}")
    private String FILES_UPLOAD_PATH;

    private final FileMapper fileMapper;

    @Override
    public void uploadFile(MultipartFile file) {
        /*********************** 文件上传 START ***********************/
        // 文件大小限制 1GB
        if (file.getSize() > 1024 * 1024 * 1024 * 8L) {
            throw new DomainException(ResultEnum.FILE_SIZE_TOO_LARGE);
        }
        // 文件名 length < 1024
        if (file.getOriginalFilename()!= null && file.getOriginalFilename().length() > 1024) {
            throw new DomainException(ResultEnum.FILE_NAME_LENGTH_TOO_LONG);
        }
        String fileName = file.getOriginalFilename();
        long fileSize = file.getSize();
        // 获取文件拓展名
        String fileExtension = "";
        if (fileName!= null) {
            int dotIndex = fileName.lastIndexOf('.');
            if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
                fileExtension = fileName.substring(dotIndex + 1);
            }
        }
        // 服务端自定义随机字符串文件名
        String uniqueFileName = UUID.randomUUID() + "." + fileExtension;
        // 指定此文件需要存放的目标目录 以日期命名（服务器目录）
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String uploadDateFolder = dateFormat.format(now);
        // 服务器唯一路径
        String serverFilePath = this.FILES_UPLOAD_PATH + "/" +  uploadDateFolder + "/" + uniqueFileName;
        File serverFile = new File(serverFilePath);
        try {
            // 确保文件夹存在
            Path fullPath = Paths.get(this.FILES_UPLOAD_PATH + "/" + uploadDateFolder);
            Files.createDirectories(fullPath);
            // 上传
            try (FileOutputStream fos = new FileOutputStream(serverFile)) {
                fos.write(file.getBytes());
            }
        } catch (IOException e) {
            // 使用自定义异常捕获异常返回信息给前端
            throw new DomainException(ResultEnum.FAIL.getCode(), e.getMessage());
        }
        /*********************** 文件上传 END ***********************/

        // 文件信息持久化
        fileMapper.insert(
                FileDO.builder().fileName(fileName)
                        .fileWholePath(serverFilePath).fileSize(fileSize).build()
        );
    }

    @Override
    public byte[] downloadFile(Long id) {
        FileDO file = fileMapper.selectById(id);
        if (file == null) {
            throw new DomainException(ResultEnum.FAIL.getCode(), "您要获取的文件不存在");
        }
        try {
            return Files.readAllBytes(Paths.get(file.getFileWholePath()));
        } catch (IOException e) {
            throw new DomainException(ResultEnum.FAIL.getCode(), e.getMessage());
        }
    }

    @Override
    public String getFileNameById(Long id) {
        FileDO file = fileMapper.selectById(id);
        return file!= null? file.getFileName() : null;
    }

    @Override
    public Boolean delete(Long id) {
        FileDO file = fileMapper.selectById(id);
        if (file == null) {
            throw new DomainException(ResultEnum.FAIL.getCode(), "数据库不存在此文件信息");
        }
        try {
            // 获取文件的完整路径
            Path filePath = Paths.get(file.getFileWholePath());
            if(filePath.toFile().exists()) {
                Files.delete(filePath);
                // 删除文件成功后，从数据库中删除文件的相关记录
                fileMapper.deleteById(id);
            }
            return true;
        } catch (IOException e) {
            throw new DomainException(ResultEnum.FAIL.getCode(), e.getMessage());
        }
    }

    @Override
    public Page<FileVO> page(FilePageReq req) {
        Page<FileDO> page = new Page<>(req.getPageParams().getPageNum(), req.getPageParams().getPageSize());
        fileMapper.selectPage(page, req.buildLambdaQueryWrapper());
        Page<FileVO> fileVOPage = new Page<>();
        // 🔵 先copy 再单另设置Records
        BeanUtils.copyProperties(page, fileVOPage);
        fileVOPage.setRecords(
                page.getRecords().stream().map(FileDO::convert2VO).collect(Collectors.toList())
        );
        return fileVOPage;
    }
}
